package com.blog.cmrpersonalblog.service.impl;

import com.blog.cmrpersonalblog.dto.dashboard.DashboardResponse;
import com.blog.cmrpersonalblog.mapper.ArticleMapper;
import com.blog.cmrpersonalblog.mapper.CommentMapper;
import com.blog.cmrpersonalblog.mapper.SysUserMapper;
import com.blog.cmrpersonalblog.mapper.UserActivityMapper;
import com.blog.cmrpersonalblog.service.DashboardService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 仪表盘服务实现类
 */
@Slf4j
@Service
public class DashboardServiceImpl implements DashboardService {

   @Resource
    private SysUserMapper sysUserMapper;

   @Resource
    private ArticleMapper articleMapper;

   @Resource
    private CommentMapper commentMapper;

   @Resource
    private UserActivityMapper userActivityMapper;

    @Override
    public DashboardResponse getDashboardData() {
        log.info("获取仪表盘数据");

        DashboardResponse response = new DashboardResponse();

        try {
            // 获取今日新增统计
            response.setTodayStats(getTodayStats());

            // 获取平台活跃度统计
            response.setActivityStats(getActivityStats());

            // 获取内容增长趋势统计
            response.setGrowthTrendStats(getGrowthTrendStats());

            log.info("仪表盘数据获取成功");
            return response;
        } catch (Exception e) {
            log.error("获取仪表盘数据失败", e);
            throw new RuntimeException("获取仪表盘数据失败：" + e.getMessage());
        }
    }

    @Override
    public DashboardResponse.TodayStats getTodayStats() {
        log.info("获取今日新增统计数据");

        DashboardResponse.TodayStats todayStats = new DashboardResponse.TodayStats();

        try {
            // 获取今日新增数据
            Long todayUsers = sysUserMapper.countTodayNewUsers();
            Long todayArticles = articleMapper.countTodayNewArticles();
            Long todayComments = commentMapper.countTodayNewComments();

            // 获取昨日新增数据
            Long yesterdayUsers = sysUserMapper.countYesterdayNewUsers();
            Long yesterdayArticles = articleMapper.countYesterdayNewArticles();
            Long yesterdayComments = commentMapper.countYesterdayNewComments();

            // 设置数据
            todayStats.setNewUsers(todayUsers != null ? todayUsers : 0L);
            todayStats.setNewArticles(todayArticles != null ? todayArticles : 0L);
            todayStats.setNewComments(todayComments != null ? todayComments : 0L);

            todayStats.setYesterdayUsers(yesterdayUsers != null ? yesterdayUsers : 0L);
            todayStats.setYesterdayArticles(yesterdayArticles != null ? yesterdayArticles : 0L);
            todayStats.setYesterdayComments(yesterdayComments != null ? yesterdayComments : 0L);

            // 计算增长率
            todayStats.setUserGrowthRate(calculateGrowthRate(todayUsers, yesterdayUsers));
            todayStats.setArticleGrowthRate(calculateGrowthRate(todayArticles, yesterdayArticles));
            todayStats.setCommentGrowthRate(calculateGrowthRate(todayComments, yesterdayComments));

            log.info("今日新增统计数据获取成功: 用户={}, 文章={}, 评论={}", todayUsers, todayArticles, todayComments);
            return todayStats;
        } catch (Exception e) {
            log.error("获取今日新增统计数据失败", e);
            throw new RuntimeException("获取今日新增统计数据失败：" + e.getMessage());
        }
    }

    @Override
    public DashboardResponse.ActivityStats getActivityStats() {
        log.info("获取平台活跃度统计数据");

        DashboardResponse.ActivityStats activityStats = new DashboardResponse.ActivityStats();

        try {
            // 获取活跃用户数据
            Long dau = userActivityMapper.countDailyActiveUsers();
            Long wau = userActivityMapper.countWeeklyActiveUsers();
            Long mau = userActivityMapper.countMonthlyActiveUsers();

            // 获取对比数据
            Long yesterdayActiveUsers = userActivityMapper.countYesterdayActiveUsers();
            Long lastWeekActiveUsers = userActivityMapper.countLastWeekActiveUsers();
            Long lastMonthActiveUsers = userActivityMapper.countLastMonthActiveUsers();

            // 设置数据
            activityStats.setDailyActiveUsers(dau != null ? dau : 0L);
            activityStats.setWeeklyActiveUsers(wau != null ? wau : 0L);
            activityStats.setMonthlyActiveUsers(mau != null ? mau : 0L);

            activityStats.setYesterdayActiveUsers(yesterdayActiveUsers != null ? yesterdayActiveUsers : 0L);
            activityStats.setLastWeekActiveUsers(lastWeekActiveUsers != null ? lastWeekActiveUsers : 0L);
            activityStats.setLastMonthActiveUsers(lastMonthActiveUsers != null ? lastMonthActiveUsers : 0L);

            // 计算增长率
            activityStats.setDauGrowthRate(calculateGrowthRate(dau, yesterdayActiveUsers));
            activityStats.setWauGrowthRate(calculateGrowthRate(wau, lastWeekActiveUsers));
            activityStats.setMauGrowthRate(calculateGrowthRate(mau, lastMonthActiveUsers));

            log.info("平台活跃度统计数据获取成功: DAU={}, WAU={}, MAU={}", dau, wau, mau);
            return activityStats;
        } catch (Exception e) {
            log.error("获取平台活跃度统计数据失败", e);
            throw new RuntimeException("获取平台活跃度统计数据失败：" + e.getMessage());
        }
    }

    @Override
    public DashboardResponse.GrowthTrendStats getGrowthTrendStats() {
        log.info("获取内容增长趋势统计数据");

        DashboardResponse.GrowthTrendStats growthTrendStats = new DashboardResponse.GrowthTrendStats();

        try {
            // 计算近7天的日期范围
            LocalDate endDate = LocalDate.now();
            LocalDate startDate = endDate.minusDays(6); // 包含今天共7天

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String startDateStr = startDate.format(formatter);
            String endDateStr = endDate.format(formatter);

            // 生成日期列表
            List<String> dates = new ArrayList<>();
            for (int i = 0; i < 7; i++) {
                dates.add(startDate.plusDays(i).format(formatter));
            }
            growthTrendStats.setDates(dates);

            // 获取每日新增数据
            List<Map<String, Object>> userTrendData = sysUserMapper.countDailyNewUsers(startDateStr, endDateStr);
            List<Map<String, Object>> articleTrendData = articleMapper.countDailyNewArticles(startDateStr, endDateStr);
            List<Map<String, Object>> commentTrendData = commentMapper.countDailyNewComments(startDateStr, endDateStr);
            List<Map<String, Object>> activeUserTrendData = userActivityMapper.countDailyActiveUserTrend(startDateStr, endDateStr);

            // 获取每日总数数据
            List<Map<String, Object>> totalUserTrendData = sysUserMapper.countDailyTotalUsers(startDateStr, endDateStr);
            List<Map<String, Object>> totalArticleTrendData = articleMapper.countDailyTotalArticles(startDateStr, endDateStr);
            List<Map<String, Object>> totalCommentTrendData = commentMapper.countDailyTotalComments(startDateStr, endDateStr);

            // 转换为趋势数据
            growthTrendStats.setUserTrend(convertToTrendList(userTrendData, dates));
            growthTrendStats.setArticleTrend(convertToTrendList(articleTrendData, dates));
            growthTrendStats.setCommentTrend(convertToTrendList(commentTrendData, dates));
            growthTrendStats.setActiveUserTrend(convertToTrendList(activeUserTrendData, dates));

            growthTrendStats.setTotalUserTrend(convertToTotalTrendList(totalUserTrendData, dates));
            growthTrendStats.setTotalArticleTrend(convertToTotalTrendList(totalArticleTrendData, dates));
            growthTrendStats.setTotalCommentTrend(convertToTotalTrendList(totalCommentTrendData, dates));

            log.info("内容增长趋势统计数据获取成功");
            return growthTrendStats;
        } catch (Exception e) {
            log.error("获取内容增长趋势统计数据失败", e);
            throw new RuntimeException("获取内容增长趋势统计数据失败：" + e.getMessage());
        }
    }

    /**
     * 计算增长率
     * @param current 当前值
     * @param previous 之前值
     * @return 增长率（百分比）
     */
    private Double calculateGrowthRate(Long current, Long previous) {
        if (previous == null || previous == 0) {
            return current != null && current > 0 ? 100.0 : 0.0;
        }
        if (current == null) {
            return -100.0;
        }
        return ((double) (current - previous) / previous) * 100.0;
    }

    /**
     * 转换为趋势列表（新增数据）
     * @param trendData 趋势数据
     * @param dates 日期列表
     * @return 趋势列表
     */
    private List<Long> convertToTrendList(List<Map<String, Object>> trendData, List<String> dates) {
        Map<String, Long> dataMap = new HashMap<>();

        // 将数据转换为Map，便于查找
        for (Map<String, Object> data : trendData) {
            Object dateObj = data.get("date");
            String date;

            // 处理不同的日期类型
            if (dateObj instanceof java.sql.Date) {
                date = ((java.sql.Date) dateObj).toString();
            } else if (dateObj instanceof java.util.Date) {
                date = new java.sql.Date(((java.util.Date) dateObj).getTime()).toString();
            } else {
                date = dateObj.toString();
            }

            Long count = ((Number) data.get("count")).longValue();
            dataMap.put(date, count);
        }

        // 按日期顺序生成趋势列表
        List<Long> trendList = new ArrayList<>();
        for (String date : dates) {
            trendList.add(dataMap.getOrDefault(date, 0L));
        }

        return trendList;
    }

    /**
     * 转换为总数趋势列表
     * @param trendData 趋势数据
     * @param dates 日期列表
     * @return 趋势列表
     */
    private List<Long> convertToTotalTrendList(List<Map<String, Object>> trendData, List<String> dates) {
        Map<String, Long> dataMap = new HashMap<>();

        // 将数据转换为Map，便于查找
        for (Map<String, Object> data : trendData) {
            Object dateObj = data.get("date");
            String date;

            // 处理不同的日期类型
            if (dateObj instanceof java.sql.Date) {
                date = ((java.sql.Date) dateObj).toString();
            } else if (dateObj instanceof java.util.Date) {
                date = new java.sql.Date(((java.util.Date) dateObj).getTime()).toString();
            } else {
                date = dateObj.toString();
            }

            Long totalCount = ((Number) data.get("totalCount")).longValue();
            dataMap.put(date, totalCount);
        }

        // 按日期顺序生成趋势列表
        List<Long> trendList = new ArrayList<>();
        for (String date : dates) {
            trendList.add(dataMap.getOrDefault(date, 0L));
        }

        return trendList;
    }
}